home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Human Interface Toolbox / Calc ControlRgn / CalcControlRgn.c next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  9.1 KB  |  248 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        Calc ControlRgn.c
  3.  
  4.     Contains:    This sample shows how to call a CDEF to get the control's Region.
  5.  
  6.     Written by: Matthew Xavier Mora    
  7.  
  8.     Copyright:    Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/19/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 02-28-96    mxm                added more comments and error checking
  21.                 05-07-96    mxm             got it ready for the cd
  22.                 
  23.  
  24. */
  25.  
  26. #include <Resources.h>
  27. #include <Errors.h>
  28. #include <Windows.h>
  29.  
  30. #include "SAL_Public.h"
  31.  
  32. #define kPaintRegionOffset     ( 200 ) 
  33. #define kNoOffset             ( 0 )
  34. #define kNextButtonOffset    ( 50 )
  35. #define kScrollBarFudge     ( 15 )
  36. #define kMemorySystemErrMsg    "\pMemory Manager error"
  37. #define    kOurWindowTitle        "\pCalculate a Control's Region Sample"
  38. #define kBadThingsMsg        "\pBad things happened"
  39.  
  40.  pascal SInt16 DoButtonHit(ButtonItemRef me, SInt32  modifiers);
  41.  
  42.  
  43. //-------------------------------------------------------------------------
  44. // This function checks MemError and reports any errors returned
  45. //-------------------------------------------------------------------------
  46.     static OSErr CheckMemoryError(void)
  47. //-------------------------------------------------------------------------
  48. {
  49.     OSErr     err;
  50.     
  51.     err = MemError();
  52.     if (err) {
  53.         SAL_ErrorMessage(kMemorySystemErrMsg,err,kSAL_NonFatalError);
  54.     }    
  55.     return err;
  56. }
  57.  
  58. //-------------------------------------------------------------------------
  59. // A utility routine to lock a Handle and report any errors. It returns the 
  60. // the state of the handle before it was locked so you can reset the handle
  61. // to its original state.
  62. //-------------------------------------------------------------------------
  63.     static OSErr MyLockHandle(Handle theHandle,SInt8 * state)
  64. //-------------------------------------------------------------------------
  65. {
  66.     OSErr     err = noErr;
  67.     SInt8     tempState;
  68.     
  69.     tempState = HGetState(theHandle);                    // remember the state
  70.     err = CheckMemoryError();                            // alert the user if error
  71.     if (err == noErr) {
  72.         HLock(theHandle);
  73.         err = CheckMemoryError();
  74.     }    
  75.     if (state) {
  76.         *state = tempState;
  77.     }
  78.     return err;
  79. }
  80.  
  81. //-------------------------------------------------------------------------
  82. // A utility routine to Set a Handle state and report any errors. 
  83. //-------------------------------------------------------------------------
  84.     static OSErr MySetHandleState(Handle theHandle,SInt8  state)
  85. //-------------------------------------------------------------------------
  86. {
  87.     OSErr     err = noErr;
  88.     
  89.     HSetState(theHandle,state);                    // remember the state
  90.     err = CheckMemoryError();                    // report any errors
  91.     return err;                                    // return error
  92. }
  93.  
  94. //-------------------------------------------------------------------------
  95. // GetControlRgn takes a control handle and an existing Rgn
  96. // as parameters and will return in the control's rgn    
  97. //-------------------------------------------------------------------------    
  98.     pascal    OSStatus GetControlRegion(ControlHandle ch,ControlPartCode     inPart,RgnHandle theRgn)
  99. //-------------------------------------------------------------------------
  100. {
  101.     #pragma unused(inPart)
  102.     Handle             cdefHandle;                                // Handle to the control Proc
  103.     SInt16             errorState = noErr ;                     // preset error state
  104.  
  105.     if ( (ch != nil) && (theRgn != nil) ) {                    // make sure we have a control and Rgn
  106.         cdefHandle = (**ch).contrlDefProc;                     // Get the control's Handle
  107.         if (!*cdefHandle) {                                    // lets load it in if its not 
  108.             LoadResource(cdefHandle);    
  109.             errorState = ResError();                        // check for error
  110.         }
  111.         if ((*cdefHandle) != nil && errorState == noErr ) { // all is well
  112.             SInt8    state ;                                    // holding place for handle state
  113.             errorState = MyLockHandle(cdefHandle,&state);    
  114.             if (errorState == noErr) {
  115.                 UInt32            result;                        // the result we don't care about
  116.                 ControlDefUPP     myControlUPP;                // Holding place for the CDEF ProcPtr or UPP
  117.                                                             //
  118.                 myControlUPP = (ControlDefUPP)(*cdefHandle); 
  119.                 // What? Casting to a UPP? Are you crazy?
  120.                 // The reason you cast in instead of creating a UPP
  121.                 // is that it may already be a UPP (ie native CDEF) 
  122.                 // and dual UPP's would really confuse Mixed Mode. If its not
  123.                 // a upp, CallControlDefProc does the right thing by passing a 
  124.                 // a valid ProcInfo to CallUniversalProc which makes
  125.                 // mixed mode a happy camper in any case.  
  126.                 result = CallControlDefProc(myControlUPP,
  127.                                             GetControlVariant(ch),
  128.                                             ch,
  129.                                             calcCntlRgn,
  130.                                             (SInt32)theRgn);
  131.                 errorState = MySetHandleState(cdefHandle,state); // reset the handle state
  132.             }
  133.         }
  134.     } else {                                                 // ControlHandle or theRgn is nil                                                
  135.         errorState  = nilHandleErr;                            // set the error
  136.     }
  137.     return (errorState);                                    // be sure and return any errors
  138. }
  139.  
  140. //-------------------------------------------------------------------------
  141. // Simple routine to paint the region we get from the Control
  142. //-------------------------------------------------------------------------
  143.     static    OSErr DisplayControlRgn(ControlHandle ch)
  144. //-------------------------------------------------------------------------
  145. {
  146.     RgnHandle    theRgn;
  147.     SInt16         err = noErr;
  148.  
  149.     theRgn = NewRgn();                        // Get a region to work with
  150.     if (theRgn) {
  151.         err = GetControlRegion(ch,0,theRgn);    // Get the Button's Region
  152.         if (err == noErr){            
  153.             OffsetRgn(theRgn,kPaintRegionOffset,kNoOffset);        
  154.             PaintRgn(theRgn);
  155.             DisposeRgn(theRgn);
  156.         } else {
  157.            err = CheckMemoryError();
  158.         }
  159.     }
  160.     return (err);
  161. }
  162.  
  163.  
  164. //-------------------------------------------------------------------------
  165. // This gets called when the Click Me button is clicked.
  166. // ------------------------------------------------------------------------
  167. // Note!
  168. // There is a problem with global optimization and call back functions.
  169. // If you want global optimization on for the rest of your code you
  170. // should turn it off for any call back functions unless MW has released
  171. //  a fix. i.e #pragma optimization_level 1
  172. //-------------------------------------------------------------------------
  173. static pascal short DoButtonHit(const ButtonItemRef me,const  long  modifiers)
  174. //-------------------------------------------------------------------------
  175. {
  176. #pragma unused (modifiers)
  177.  
  178.     ControlHandle     cr  = nil;
  179.     OSErr         err = noErr;
  180.     
  181.     cr = (ControlHandle) SAL_GetObjectHandle((SInt32) me);     
  182.     if (cr) {
  183.         err = DisplayControlRgn(cr);
  184.         if (err != noErr) {
  185.             SAL_ErrorMessage(kBadThingsMsg,err,kSAL_NonFatalError);
  186.         }
  187.     }
  188.     return err;
  189. }
  190.  
  191. //-------------------------------------------------------------------------
  192. // This gets called when the Clear button is clicked.
  193. //-------------------------------------------------------------------------
  194. static pascal SInt16 DoClear(const ButtonItemRef me,const SInt32  modifiers)
  195. //-------------------------------------------------------------------------
  196. {
  197. #pragma unused (modifiers)
  198. #pragma unused (me)
  199.     Rect r;
  200.     
  201.     r = gSAL_CurrentWindow->portRect;             // Get the window's portRect
  202.     r.left      += kPaintRegionOffset;                // offset so it doesn't erase
  203.     r.right  -= kScrollBarFudge;                // our buttons and scroll bar
  204.     r.bottom -= kScrollBarFudge;                // areas
  205.     InvalRect(&r);                                 
  206.     return noErr;                                
  207. }
  208.  
  209. //-------------------------------------------------------------------------
  210. // This is the main function. Note how simple it is. It installs
  211. // two Buttons and then lets SimpleApp handle the rest. 
  212. // 
  213. //-------------------------------------------------------------------------
  214.     void main(void)
  215. //-------------------------------------------------------------------------
  216. {
  217.     Rect     r;
  218.     SInt16     gMyWindowID;
  219.     SInt16     err;
  220.     
  221.     SAL_InitSimpleApp(1,kSAL_UseStandardMenu);    // Simple App Sets up the Tool Box For us 
  222.     gMyWindowID = SAL_GetDocumentWindow(128,nil); // Get our stored window 
  223.                                                 // the global gSAL_CurrentWindow is maintained
  224.                                                 // by SimpleApp and it contains the active
  225.                                                 // document window reference
  226.     SetWTitle(gSAL_CurrentWindow,kOurWindowTitle);// set the window title so we know what we are running
  227.     SetRect(&r,10,30,100,50);                    // set the control bounds
  228.     err = SAL_InstallPushButton (0,                // Reference ID (we don't care)
  229.                              gSAL_CurrentWindow,    // Owner Window 
  230.                              "\pClick Me",        // Name
  231.                              &r,                // Bounds                        
  232.                              kSAL_NoCommandKey,    // Command Key
  233.                              DoButtonHit ,        // Button Hit 
  234.                              nil                // Button Update Proc 
  235.                              );
  236.     OffsetRect(&r,kNoOffset,kNextButtonOffset);                         
  237.     err = SAL_InstallPushButton (0,                // Reference ID (we don't care)
  238.                              gSAL_CurrentWindow,    // Owner Window
  239.                              "\pClear",            // Name
  240.                              &r,                // Bounds                        
  241.                              kSAL_NoCommandKey,    // Command Key
  242.                              DoClear ,            // Button Hit Proc
  243.                              nil                // Button Update Proc
  244.                              );
  245.     SAL_Run();                                    // Let SimpleApp handle the rest
  246. }
  247.  
  248.